package com.yonyou.pmclouds.projectpart.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoInsertProcessor;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoUpdateProcessor;
import com.yonyou.pmclouds.basecom.bp.processor.BdReferenceChecker;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.consts.EnableStatusConst;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.ConcurrentOperationException;
import com.yonyou.pmclouds.basecom.exception.DataReferencedException;
import com.yonyou.pmclouds.basecom.lock.AutoReleaseLockUtil;
import com.yonyou.pmclouds.basecom.ref.itf.RefCodeConst;
import com.yonyou.pmclouds.basecom.ref.itf.ReferenceChecker;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.projectpart.entity.ProjectPartVO;
import com.yonyou.pmclouds.projectpart.mapper.ProjectpartMapper;
import com.yonyou.pmclouds.projectpart.processor.ProjectpartCodeCheckProcessor;
import com.yonyou.pmclouds.projectpart.processor.ProjectpartDeleteCheckProcessor;
import com.yonyou.pmclouds.projectpart.processor.ProjectpartFillDataProcessor;
import com.yonyou.pmclouds.projectpart.processor.ProjectpartUpdateChildrenCodeProcessor;
import com.yonyou.pmclouds.projectpart.service.IProjectpartService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Slf4j
@Service(interfaceClass = IProjectpartService.class, version = ApplicationConsts.APPLICATION_VERSION)
public class ProjectpartServiceImpl implements IProjectpartService {
    public static final String LOCK_PREFIX = "projectpart_";
    @Autowired
    private ProjectpartMapper projectpartMapper;
    @Autowired
    private ProjectpartCodeCheckProcessor projectpartCodeCheckProcessor;
    @Autowired
    private ProjectpartFillDataProcessor projectpartFillDataProcessor;
    @Autowired
    private ProjectpartDeleteCheckProcessor projectpartDeleteCheckProcessor;
    @Autowired
    private ProjectpartUpdateChildrenCodeProcessor projectpartUpdateChildrenCodeProcessor;
    @Autowired
    private ReferenceChecker referenceChecker;

    @Override
    public ProjectPartVO insert(ProjectPartVO projectpartVO) throws BusinessException {
        //  add lock
        if (!AutoReleaseLockUtil.addAutoReleaseLock(LOCK_PREFIX + projectpartVO.getPkTenant()+"_"+projectpartVO.getPkProject())) {
            throw new ConcurrentOperationException();
        }
        projectpartVO.setEnableStatus(EnableStatusConst.ENABLE);
        projectpartVO.setPkTenant(RuntimeEnvironment.getTenantId());
        SingleInsertBpTemplate<ProjectPartVO> bp = new SingleInsertBpTemplate<ProjectPartVO>(projectpartMapper);
        // 校验编码重复(同一项目下，是否重复)
        bp.addBeforeProcessor(projectpartCodeCheckProcessor);
        // 填充内码
        bp.addBeforeProcessor(projectpartFillDataProcessor);
        // 添加审计信息
        bp.addBeforeProcessor(new AuditInfoInsertProcessor<ProjectPartVO>());
        bp.insert(projectpartVO);
        return projectpartVO;
    }

    @Override
    public ProjectPartVO insertForMobile(ProjectPartVO projectPartVO) throws BusinessException {
        //  add lock
        if (!AutoReleaseLockUtil.addAutoReleaseLock(LOCK_PREFIX + projectPartVO.getPkTenant()+"_"+projectPartVO.getPkProject())) {
            throw new ConcurrentOperationException();
        }
        projectPartVO.setEnableStatus(EnableStatusConst.ENABLE);
        SingleInsertBpTemplate<ProjectPartVO> bp = new SingleInsertBpTemplate<ProjectPartVO>(projectpartMapper);
        // 填充内码
        bp.addBeforeProcessor(projectpartFillDataProcessor);
        // 添加审计信息
        bp.addBeforeProcessor(new AuditInfoInsertProcessor<ProjectPartVO>());
        bp.insert(projectPartVO);
        return projectPartVO;
    }
    @Override
    public ProjectPartVO update(ProjectPartVO projectpartVO) throws BusinessException {
        //  add lock
        if (!AutoReleaseLockUtil.addAutoReleaseLock(LOCK_PREFIX + projectpartVO.getPkTenant()+"_"+projectpartVO.getPkProject())) {
            throw new ConcurrentOperationException();
        }
        SingleUpdateBpTemplate<ProjectPartVO> bp = new SingleUpdateBpTemplate<ProjectPartVO>(projectpartMapper,
                new String[]{CommonFieldConst.SNAME,CommonFieldConst.SCODE});
        // 校验编码重复(同一项目下，是否重复)
        bp.addBeforeProcessor(projectpartCodeCheckProcessor);
        //级联更新所有子级编码
        bp.addBeforeProcessor(projectpartUpdateChildrenCodeProcessor);
        // 添加审计信息
        bp.addBeforeProcessor(new AuditInfoUpdateProcessor<ProjectPartVO>());
        bp.update(projectpartVO);
        return projectpartVO;
    }
    @Override
    public ProjectPartVO checkReference(ProjectPartVO projectPartVO) throws BusinessException {
        BdReferenceChecker checker = new BdReferenceChecker<ProjectPartVO>(RefCodeConst.PROJECTPART, referenceChecker);
        try {
            checker.process(projectPartVO,null);
        }catch (BusinessException e){
            if(e instanceof DataReferencedException){
                throw new BusinessException("如果修改所选数据，将会影响该数据做的所有单据引用数据，是否继续修改？");
            }
            throw e;
        }
        return projectPartVO;
    }

    @Override
    public ProjectPartVO delete(ProjectPartVO projectpartVO) throws BusinessException {
        //  add lock
        if (!AutoReleaseLockUtil.addAutoReleaseLock(LOCK_PREFIX + RuntimeEnvironment.getTenantId()+"_"+projectpartVO.getPkProject()+"_"+projectpartVO.getPkProjectpart())) {
            throw new ConcurrentOperationException();
        }
        SingleDeleteBpTemplate<ProjectPartVO> bp = new SingleDeleteBpTemplate<ProjectPartVO>(projectpartMapper);
        bp.addBeforeProcessor(projectpartDeleteCheckProcessor);
        bp.addBeforeProcessor(new BdReferenceChecker<ProjectPartVO>(RefCodeConst.PROJECTPART, referenceChecker));
        return bp.delete(projectpartVO);
    }

    @Override
    public ProjectPartVO updateEnableStatus(ProjectPartVO projectPartVO) throws BusinessException {
        if(StringUtils.isEmpty(projectPartVO.getPkProjectpart()) || StringUtils.isEmpty(projectPartVO.getInnerCode())){
            throw new BusinessException("参数错误，请检查");
        }
        SingleUpdateBpTemplate<ProjectPartVO> bp = new SingleUpdateBpTemplate<ProjectPartVO>(projectpartMapper,
                new String[]{ProjectPartVO.ENABLE_STATUS});
        // 添加审计信息
        bp.addBeforeProcessor(new AuditInfoUpdateProcessor<ProjectPartVO>());
        bp.update(projectPartVO);
        if(projectPartVO.getEnableStatus().equals(EnableStatusConst.ENABLE)){
            //启用，只启用当前节点，停用，需要停用当前节点以及下级
            return projectPartVO;
        }
        ProjectPartVO qryVO = new ProjectPartVO();
        qryVO.setPkProject(projectPartVO.getPkProject());
        qryVO.setInnerCode(projectPartVO.getInnerCode()+"%");
        qryVO.setInnerCodeLen(projectPartVO.getInnerCode().length());
        List<ProjectPartVO> dbResult = projectpartMapper.queryVOsByCondition(qryVO);
        if(!CollectionUtils.isEmpty(dbResult)){
            for(ProjectPartVO vo : dbResult){
                vo.setEnableStatus(projectPartVO.getEnableStatus());
                bp.update(vo);
            }
        }
        return projectPartVO;
    }
}
